﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Xml;
using SHomeWorkshop.LunarConcept.Adorners;
using SHomeWorkshop.LunarConcept.Controls;
using SHomeWorkshop.LunarConcept.Enums;
using SHomeWorkshop.LunarConcept.Tools;
using SHomeWorkshop.LunarConcept.Widgets.Interfaces;
using System.Collections.Generic;
using SHomeWorkshop.LunarMind;

namespace SHomeWorkshop.LunarConcept.Widgets
{
    /// <summary>
    /// 创建时间：2012年1月20日前
    /// 创建者：  杨震宇
    /// 
    /// 主要用途：提供一个矩形部件。
    /// </summary>
    public class RectangleWidget : ShapeWidget, ICanSameSize, ICanBeLinkedWidget, ITextRotate, IRadius
    {
        #region 构造方法=====================================================================================================

        /// <summary>
        /// [静态构造方法]
        /// </summary>
        static RectangleWidget()
        {
            dashArray = new DoubleCollection() { 2, 2 };
        }

        /// <summary>
        /// [构造方法]
        /// </summary>
        /// <param name="pageEditor"></param>
        public RectangleWidget(PageEditorReader editor)
            : base(editor)
        {
            widgetType = Enums.WidgetTypes.Rectangle;
            widgetClassLocalName = Widget.GetWidgetClassLocalName(this.GetType().Name);

            mainRectangle.Fill = null;
            mainRectangle.Stroke = WidgetForeColor;

            this.mainCanvas.Children.Add(mainRectangle);

            Canvas.SetZIndex(mainRectangle, 0);

            this.commentAdorner = new CommentAdorner(this.mainRectangle, this) { Visibility = System.Windows.Visibility.Collapsed };//默认不显示。

            this.hyperLinkAdorner = new HyperLinkAdorner(this.mainRectangle, this) { Visibility = Visibility.Collapsed };
            this.hyperLinkAdorner.MouseLeftButtonUp += new MouseButtonEventHandler(hyperLinkAdorner_MouseLeftButtonUp);

            AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(this.mainCanvas);
            if (adornerLayer == null)
            {
                MessageBox.Show("　　未找到Widget的装饰层！", Globals.AppName, MessageBoxButton.OK, MessageBoxImage.Warning);
            }
            else
            {
                //这个要放在最底层
                this.presentationAreaAdorner = new PresentationAreaAdorner(this.MainCanvas, this);
                adornerLayer.Add(presentationAreaAdorner);

                //添加标记装饰层
                this.markAdorner = new RectangleMarkAdorner(this.mainCanvas, this);
                adornerLayer.Add(markAdorner);

                adornerLayer.Add(this.commentAdorner);//这个要在各具体部件类中添加。
                adornerLayer.Add(this.hyperLinkAdorner);//这个要在各具体部件类中添加。
            }
            
            //最后添加文本面板。
            this.mainCanvas.Children.Add(this.mainTextPanel);
            Canvas.SetZIndex(this.mainTextPanel, 2);
        }

        #endregion


        #region 字段与属性===================================================================================================

        public override Point BottomRight
        {
            get
            {
                double minLeft, minTop, maxRight, maxBottom;

                minLeft = Math.Min(startPoint.X, endPoint.X);
                maxRight = Math.Max(startPoint.X, endPoint.X);

                minTop = Math.Min(startPoint.Y, endPoint.Y);
                maxBottom = Math.Max(startPoint.Y, endPoint.Y);

                return new Point(maxRight, maxBottom);
            }
        }

        /// <summary>
        /// 点划线定义。
        /// </summary>
        private static DoubleCollection dashArray;
        
        private Point EndBasePoint
        {
            get
            {
                return new Point(Math.Max(startPoint.X, endPoint.X), Math.Max(startPoint.Y, endPoint.Y));
            }
        }
        
        private Point endPoint = new Point();
        /// <summary>
        /// [读写]终点。
        /// </summary>
        [Tools.LunarProperty("EndPoint", PropertyDateType.Point)]
        public Point EndPoint
        {
            get { return endPoint; }
            set
            {
                endPoint = value;
                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.EndPointTag, value.ToString());
                }

                RefreshLocation();
            }
        }

        private bool fixTextWidth = false;
        /// <summary>
        /// [读写]是否绑定文本块最大宽度。（文本块最小宽度为20）。
        /// </summary>
        [Tools.LunarProperty("FixTextWidth", PropertyDateType.Bool)]
        public bool FixTextWidth
        {
            get { return fixTextWidth; }
            set
            {
                fixTextWidth = value;
                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.FixTextWidthTag, fixTextWidth.ToString());
                }

                RefreshFixTextWidth();
            }
        }

        protected double radius = 0.0;
        /// <summary>
        /// [读写]是否圆角矩形。
        /// </summary>
        [Tools.LunarProperty("Radius", PropertyDateType.Double)]
        public double Radius
        {
            get
            {
                return this.radius;
            }
            set
            {
                radius = value;
                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.RadiusTag, radius.ToString());
                }

                RefreshRadius(this.OuterRect);
            }
        }

        /// <summary>
        /// [只读]表示当前部件是否被某个连接线挂接着。
        /// </summary>
        public bool IsLinked
        {
            get
            {
                if (this.masterEditor == null) return false;

                foreach (UIElement ue in this.masterEditor.Children)
                {
                    ILinkableLine linkedLine = ue as ILinkableLine;
                    if (linkedLine == null) continue;

                    if (linkedLine.StartMasterId == this.id || linkedLine.EndMasterId == this.id) return true;
                }

                return false;
            }
        }

        private bool isMarkTextCollapsed = false;
        /// <summary>
        /// [读写]是否折叠显示右下角的标记文本（一般用作选择题答案）。
        /// </summary>
        [Tools.LunarProperty("IsMarkTextCollapsed", PropertyDateType.Bool)]
        public bool IsMarkTextCollapsed
        {
            get { return isMarkTextCollapsed; }
            set
            {
                isMarkTextCollapsed = value;
                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.IsMarkTextCollapsedTag, isMarkTextCollapsed.ToString());
                }
                this.RefreshMarkText();
            }
        }
       
        [Tools.LunarProperty("WidgetLineWidth", PropertyDateType.Double)]
        public override double WidgetLineWidth
        {
            get
            {
                return base.WidgetLineWidth;
            }
            set
            {
                base.WidgetLineWidth = value;
                this.RefreshMarkText();
            }
        }

        private Rectangle mainRectangle = new Rectangle() { Cursor = Cursors.Hand };
        /// <summary>
        /// [只读]用以呈现的矩形。
        /// </summary>
        public Rectangle MainRectangle
        {
            get { return mainRectangle; }
        }

        /// <summary>
        /// 显示“ＡＢＣＤ”等字母的装饰器（用来显示客观题的答案）。
        /// </summary>
        private RectangleMarkAdorner markAdorner;

        private string markText = string.Empty;
        /// <summary>
        /// [读写]标记文本。一般用于显示客观题答案。
        /// </summary>
        [Tools.LunarProperty("MarkText", PropertyDateType.String)]
        public string MarkText
        {
            get { return markText; }
            set
            {
                this.markText = value;

                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.MarkTextTag, value);
                }

                this.RefreshMarkText();
            }
        }

        private PresentationAreaAdorner presentationAreaAdorner;

        private bool isPresentationArea = false;
        /// <summary>
        /// [读写]是否演示区域。如为真，则“按路径演示”会演示此矩形部件所在区域（但不会演示此矩形本身）。
        /// </summary>
        [Tools.LunarProperty("IsPresentationArea", PropertyDateType.Bool)]
        public bool IsPresentationArea
        {
            get
            {
                return isPresentationArea;
            }

            set
            {
                isPresentationArea = value;

                this.xmlData?.SetAttribute(XmlTags.IsPresentationAreaTag, value.ToString());

                this.RefreshIsPresentationArea();
            }
        }

        private string iconXamlText = string.Empty;
        /// <summary>
        /// [读写]用于存储Xaml文本，此文本用于自动载入为新图标。
        /// </summary>
        [Tools.LunarProperty("IconXamlText", PropertyDateType.String)]
        public string IconXamlText
        {
            get { return iconXamlText; }
            set
            {
                this.iconXamlText = value;
                if (this.xmlData != null)
                {
                    XmlNode iconXamlNode = this.xmlData.SelectSingleNode(XmlTags.IconXamlTextTag);
                    if (iconXamlNode == null)
                    {
                        this.xmlData.AppendXmlAsChild("<" + XmlTags.IconXamlTextTag + ">" + value + "</" + XmlTags.IconXamlTextTag + ">");
                    }
                    else
                    {
                        iconXamlNode.InnerXml = value;
                    }
                }

                this.RefreshIconXamlText();
            }
        }

        private Rect movingRect;
        /// <summary>
        /// 部件正在被拖动时的外边框。
        /// </summary>
        public Rect MovingRect
        {
            get
            {
                return movingRect;
            }
        }

        /// <summary>
        /// 返回文本区的实际高度。
        /// </summary>
        public double TextPanelHeight
        {
            get
            {
                if (this.mainTextPanel != null)
                {
                    this.mainTextPanel.InvalidateArrange();
                    this.mainTextPanel.UpdateLayout();
                    return this.mainTextPanel.ActualHeight;
                    //return this.mainTextPanel.RenderSize.Height;//取不到及时的值。
                }
                else return 0;
            }
        }


        private double textRotateAngle = 0;
        /// <summary>
        /// [读写]文本旋转角度。取值范围：[-180,180]。
        /// </summary>
        [Tools.LunarProperty("TextRotateAngle", PropertyDateType.Double)]
        public double TextRotateAngle
        {
            get { return textRotateAngle; }
            set
            {
                if (value > 180)
                {
                    textRotateAngle = 180;
                }
                else if (value < -180)
                {
                    textRotateAngle = -180;
                }
                else
                {
                    textRotateAngle = value;
                }

                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.TextRotateAngleTag, textRotateAngle.ToString());
                }

                this.RefreshTextRotateAngle();
            }
        }

        private Enums.TextAreaAlignment textAreaAlignment = TextAreaAlignment.Center;
        /// <summary>
        /// [读写]文本区域在“自动折行”被关闭的情况下，如何对齐文本区域（不是文本区域内部文本段落的对齐）。
        /// </summary>
        [Tools.LunarProperty("TextAreaAlignment", PropertyDateType.TextAreaAlignment)]
        public Enums.TextAreaAlignment TextAreaAlignment
        {
            get { return textAreaAlignment; }
            set
            {
                textAreaAlignment = value;
                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.TextAreaAlignmentTag, this.textAreaAlignment.ToString());
                }
                RefreshTextPanelLocatin();
            }
        }

        private Point StartBasePoint
        {
            get
            {
                return new Point(Math.Min(startPoint.X, endPoint.X), Math.Min(startPoint.Y, endPoint.Y));
            }
        }
        
        private Point startPoint = new Point();
        /// <summary>
        /// [读写]起点。
        /// </summary>
        [Tools.LunarProperty("StartPoint", PropertyDateType.Point)]
        public Point StartPoint
        {
            get { return startPoint; }
            set
            {
                startPoint = value;
                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.StartPointTag, value.ToString());
                }

                RefreshLocation();
            }
        }

        public override Point TopLeft
        {
            get
            {
                double minLeft, minTop, maxRight, maxBottom;

                minLeft = Math.Min(startPoint.X, endPoint.X);
                maxRight = Math.Max(startPoint.X, endPoint.X);

                minTop = Math.Min(startPoint.Y, endPoint.Y);
                maxBottom = Math.Max(startPoint.Y, endPoint.Y);

                return new Point(minLeft, minTop);
            }
        }

        #endregion


        #region 方法=========================================================================================================

        /// <summary>
        /// 根据XmlData的信息，生成部件内容，设置部件格式。
        /// </summary>
        public override void Build()
        {
            base.Build();

            if (this.xmlData == null) return;

            XmlAttribute attrStartPoint = this.xmlData.GetAttribute(XmlTags.StartPointTag);
            if (attrStartPoint != null)
            {
                this.startPoint = Point.Parse(attrStartPoint.Value);
            }

            XmlAttribute attrEndPoint = this.xmlData.GetAttribute(XmlTags.EndPointTag);
            if (attrEndPoint != null)
            {
                this.endPoint = Point.Parse(attrEndPoint.Value);
            }

            XmlAttribute attrFixTextWidth = this.xmlData.GetAttribute(XmlTags.FixTextWidthTag);
            if (attrFixTextWidth != null)
            {
                this.fixTextWidth = bool.Parse(attrFixTextWidth.Value);
            }

            XmlAttribute attrRadius = this.xmlData.GetAttribute(XmlTags.RadiusTag);
            if (attrRadius != null)
            {
                this.radius = double.Parse(attrRadius.Value);
            }

            XmlAttribute attrIsMarkTextCollapsed = this.xmlData.GetAttribute(XmlTags.IsMarkTextCollapsedTag);
            if (attrIsMarkTextCollapsed != null)
            {
                this.isMarkTextCollapsed = bool.Parse(attrIsMarkTextCollapsed.Value);
            }

            XmlAttribute attrMark = this.xmlData.GetAttribute(XmlTags.MarkTextTag);
            if (attrMark != null)
            {
                this.markText = attrMark.Value;
            }
            else
            {
                this.markText = string.Empty;
            }

            var attrIsPresentationArea = this.xmlData.GetAttribute(XmlTags.IsPresentationAreaTag);
            if (attrIsPresentationArea != null)
            {
                this.isPresentationArea = bool.Parse(attrIsPresentationArea.Value);
            }

            XmlAttribute attrTextRotateAngle = this.xmlData.GetAttribute(XmlTags.TextRotateAngleTag);
            if (attrTextRotateAngle != null)
            {
                this.textRotateAngle = double.Parse(attrTextRotateAngle.Value);
            }
            else
            {
                this.textRotateAngle = 0;
            }

            XmlAttribute attrTextAreaAlignment = this.xmlData.GetAttribute(XmlTags.TextAreaAlignmentTag);
            if (attrTextAreaAlignment != null)
            {
                this.textAreaAlignment = (Enums.TextAreaAlignment)Enum.Parse(typeof(Enums.TextAreaAlignment), attrTextAreaAlignment.Value);
            }
            else
            {
                this.textAreaAlignment = Enums.TextAreaAlignment.Center;
            }

            XmlNode iconXamlNode = this.xmlData.SelectSingleNode(XmlTags.IconXamlTextTag);
            if (iconXamlNode != null)
            {
                this.iconXamlText = iconXamlNode.InnerXml;
            }

            this.RefreshTextRotateAngle();

            this.RefreshLocation();//已含this.RefreshIsRoundRectangle();
            this.RefreshMarkText();

            this.RefreshRadius(this.OuterRect);
            this.RefreshIconXamlText();

            //此类是下面这几个属性的“最终实现类”。这些属性的值都已在基类确定。因此调用,
            this.RefreshWidgetBackColor();
            this.RefreshIsPresentationArea();    // 这个必须在 RefreshWidgetBackColor() 后面。

            this.RefreshWidgetLineColor();
            this.RefreshWidgetLineWidth();
            this.RefreshLineDash();
            this.RefreshRadius(this.OuterRect);
        }

        private void DrawLine()
        {
            DrawLine(this.startPoint, this.endPoint, false);
        }

        /// <param name="startPoint">首端点。</param>
        /// <param name="endPoint">尾端点。</param>
        /// <param name="isShift">是否按住Shift键拖动。</param>
        private void DrawLine(Point startPoint, Point endPoint, bool isShift)
        {
            Point startBasePt, endBasePt;

            startBasePt = new Point(Math.Min(startPoint.X, endPoint.X),
                   Math.Min(startPoint.Y, endPoint.Y));
            endBasePt = new Point(Math.Max(startPoint.X, endPoint.X),
              Math.Max(startPoint.Y, endPoint.Y));

            if (isShift)
            {
                if (startPoint.Y > endPoint.Y)
                {
                    endBasePt.Y = startBasePt.Y + (endBasePt.X - startBasePt.X);
                }
                else
                {
                    startBasePt.Y = endBasePt.Y - (endBasePt.X - startBasePt.X);
                }
            }

            Canvas.SetLeft(mainRectangle, startBasePt.X);
            Canvas.SetTop(mainRectangle, startBasePt.Y);

            mainRectangle.Width = (endBasePt.X - startBasePt.X);
            mainRectangle.Height = (endBasePt.Y - startBasePt.Y);

            //刷新圆角。
            this.RefreshRadius(new Rect(startBasePt, endBasePt));

            //移动部件控制点时，要刷新连接线的。
            this.movingRect = new Rect(startBasePt, endBasePt);
            
            LocateTextPanel(startBasePt, endBasePt);
            LocateXamlIcon(startBasePt, endBasePt);

            this.RefreshMarkText(new Rect(startPoint, endPoint));
        }

        private void LocateXamlIcon(Point startBasePt, Point endBasePt)
        {
            if (this.xamlIconFrameWorkElement != null)
            {
                Canvas.SetLeft(this.xamlIconFrameWorkElement, Math.Min(startBasePt.X, endBasePt.X));
                Canvas.SetTop(this.xamlIconFrameWorkElement, Math.Min(startBasePt.Y, endBasePt.Y));

                this.xamlIconFrameWorkElement.Width = Math.Abs(endBasePt.X - startBasePt.X);
                this.xamlIconFrameWorkElement.Height = Math.Abs(endBasePt.Y - startBasePt.Y);
            }
        }

        /// <summary>
        /// 重定文本位置。
        /// </summary>
        /// <param name="startBasePt">首端基准点。</param>
        /// <param name="endBasePt">尾基准点。</param>
        private void LocateTextPanel(Point startBasePt, Point endBasePt)
        {
            RefreshFixTextWidth(startBasePt, endBasePt);//注意顺序。

            Point center = new Point(startBasePt.X + (endBasePt.X - startBasePt.X) / 2,
                startBasePt.Y + (endBasePt.Y - startBasePt.Y) / 2);

            Point textStart;

            if (fixTextWidth)
            {
                textStart = new Point(center.X - this.mainTextPanel.ActualWidth / 2 - this.mainTextPanel.Margin.Left,
                    Math.Min(startBasePt.Y, endBasePt.Y) + 2 - this.mainTextPanel.Margin.Top + this.widgetLineWidth);
            }
            else
            {
                switch (this.textAreaAlignment)
                {
                    case Enums.TextAreaAlignment.Left:
                        {
                            textStart = new Point(startBasePt.X, center.Y - this.mainTextPanel.ActualHeight / 2 - this.mainTextPanel.Margin.Top);
                            break;
                        }
                    case Enums.TextAreaAlignment.Right:
                        {
                            textStart = new Point(endBasePt.X - this.mainTextPanel.ActualWidth - this.mainTextPanel.Margin.Left - this.mainTextPanel.Margin.Right,
                                center.Y - this.mainTextPanel.ActualHeight / 2 - this.mainTextPanel.Margin.Top);
                            break;
                        }
                    case Enums.TextAreaAlignment.Top:
                        {
                            textStart = new Point(center.X - this.mainTextPanel.ActualWidth / 2 - this.mainTextPanel.Margin.Left, startBasePt.Y);
                            break;
                        }
                    case Enums.TextAreaAlignment.Bottom:
                        {
                            textStart = new Point(center.X - this.mainTextPanel.ActualWidth / 2 - this.mainTextPanel.Margin.Left,
                                endBasePt.Y - this.mainTextPanel.ActualHeight - this.mainTextPanel.Margin.Top - this.mainTextPanel.Margin.Bottom);
                            break;
                        }
                    case Enums.TextAreaAlignment.TopLeft:
                        {
                            textStart = startBasePt; break;
                        }
                    case Enums.TextAreaAlignment.TopRight:
                        {
                            textStart = new Point(endBasePt.X - this.mainTextPanel.ActualWidth - this.mainTextPanel.Margin.Left - this.mainTextPanel.Margin.Right,
                                startBasePt.Y);
                            break;
                        }
                    case Enums.TextAreaAlignment.BottomLeft:
                        {
                            textStart = new Point(startBasePt.X,
                                endBasePt.Y - this.mainTextPanel.ActualHeight - this.mainTextPanel.Margin.Top - this.mainTextPanel.Margin.Bottom);
                            break;
                        }
                    case Enums.TextAreaAlignment.BottomRight:
                        {
                            textStart = new Point(endBasePt.X - this.mainTextPanel.ActualWidth - this.mainTextPanel.Margin.Left - this.mainTextPanel.Margin.Right,
                                endBasePt.Y - this.mainTextPanel.ActualHeight - this.mainTextPanel.Margin.Top - this.mainTextPanel.Margin.Bottom);
                            break;
                        }
                    default:
                        {
                            //textStart = new Point(endBasePt.X - this.mainTextPanel.ActualWidth - this.mainTextPanel.Margin.Left - this.mainTextPanel.Margin.Right,
                            //    endBasePt.Y - this.mainTextPanel.ActualHeight - this.mainTextPanel.Margin.Top - this.mainTextPanel.Margin.Bottom);

                            string backColorName = BrushManager.GetName(widgetBackColor);
                            if (backColorName.Contains("Bubble"))
                            {
                                double offset = Math.Abs(endBasePt.Y - startBasePt.Y) / 16;
                                //气泡背景，有个偏移量。
                                //要保证气泡中的文字垂直对齐，测试得出的偏移量约值是16分之1。

                                if (backColorName.Contains("Top"))
                                {
                                    textStart = new Point(center.X - this.mainTextPanel.ActualWidth / 2 - this.mainTextPanel.Margin.Left,
                                        center.Y - this.mainTextPanel.ActualHeight / 2 - this.mainTextPanel.Margin.Top + offset);
                                }
                                else
                                {
                                    textStart = new Point(center.X - this.mainTextPanel.ActualWidth / 2 - this.mainTextPanel.Margin.Left,
                                        center.Y - this.mainTextPanel.ActualHeight / 2 - this.mainTextPanel.Margin.Top - offset);
                                }
                            }
                            else
                            {
                                textStart = new Point(center.X - this.mainTextPanel.ActualWidth / 2 - this.mainTextPanel.Margin.Left,
                                    center.Y - this.mainTextPanel.ActualHeight / 2 - this.mainTextPanel.Margin.Top);
                            }

                            break;
                        }
                }
            }

            Canvas.SetLeft(this.mainTextPanel, textStart.X);
            Canvas.SetTop(this.mainTextPanel, textStart.Y);
        }
        
        /// <summary>
        /// 这个虚方法是用以查看本部件是否在选定框的内部。
        /// 线型部件，各有各的计算办法。
        /// </summary>
        /// <param name="rect"></param>
        /// <returns></returns>
        public override bool IsInRect(Rect rect)
        {
            //return base.IsInRect(rect);//这个要屏蔽。
            bool isInRect = base.IsInRect(rect);
            if (isInRect)
            {
                return true;
            }
            else
            {
                Rect virtualRect = new Rect(startPoint, endPoint);
                return rect.IntersectsWith(virtualRect);
            }
        }
        
        /// <summary>
        /// 取与自身挂接的连接线。
        /// </summary>
        /// <returns>可能返回null。</returns>
        public List<ILinkableLine> GetLinkedLines()
        {
            if (this.masterEditor == null) return null;

            List<Widget> widgets = new List<Widget>();
            widgets.Add(this);

            return this.masterEditor.GetLinkedLines(widgets);
        }

        public override string GetRelativeOuterXml(Point baseCopyTopLeft)
        {
            if (this.xmlData == null) return string.Empty;

            Point oldStartPoint = startPoint;
            Point newStartPoint = new Point(oldStartPoint.X - baseCopyTopLeft.X,
                oldStartPoint.Y - baseCopyTopLeft.Y);
            this.xmlData.SetAttribute(XmlTags.StartPointTag, newStartPoint.ToString());

            Point oldEndPoint = endPoint;
            Point newEndPoint = new Point(oldEndPoint.X - baseCopyTopLeft.X,
                oldEndPoint.Y - baseCopyTopLeft.Y);
            this.xmlData.SetAttribute(XmlTags.EndPointTag, newEndPoint.ToString());

            System.Text.StringBuilder sb = new System.Text.StringBuilder();
            sb.Append(this.xmlData.OuterXml);

            this.xmlData.SetAttribute(XmlTags.StartPointTag, oldStartPoint.ToString());
            this.xmlData.SetAttribute(XmlTags.EndPointTag, oldEndPoint.ToString());

            return sb.ToString();
        }

        public override void RefreshLineDash()
        {
            switch (lineDash)
            {
                case LineDashType.DashType.Dash:
                    {
                        this.mainRectangle.StrokeDashArray = LineDashType.dashCollection; break;
                    }
                case LineDashType.DashType.DashDotDot:
                    {
                        this.mainRectangle.StrokeDashArray = LineDashType.dashDotDotCollection; break;
                    }
                case LineDashType.DashType.Dot:
                    {
                        this.mainRectangle.StrokeDashArray = LineDashType.dotCollection; break;
                    }
                case LineDashType.DashType.Solid:
                    {
                        this.mainRectangle.StrokeDashArray = LineDashType.solidCollection; break;
                    }
                default:
                    {
                        this.mainRectangle.StrokeDashArray = LineDashType.dashDotCollection; break;
                    }
            }
        }

        /// <summary>
        /// 此方法本是专门为矩形提供的，用于在EditorManager.DefaultFontSize发生变化时刷新相关的值。
        /// </summary>
        public override void RefreshDefaultFontSize()
        {
            base.RefreshDefaultFontSize();

            this.RefreshMarkText();//使用了EditorManager.DefaultFontSize.
        }

        /// <summary>
        /// 在移动控制点时刷新文本面板宽度。
        /// </summary>
        private void RefreshFixTextWidth()
        {
            RefreshFixTextWidth(this.StartBasePoint, this.EndBasePoint);
        }

        private void RefreshFixTextWidth(Point startBasePt, Point endBasePt)
        {
            if (fixTextWidth)
            {
                double rectangleWidth = Math.Abs(endBasePt.X - startBasePt.X);

                if (rectangleWidth < 24)
                {
                    this.mainTextPanel.Width = 20;
                }
                else
                {
                    this.mainTextPanel.Width = rectangleWidth - 4 - this.widgetLineWidth * 2;
                }

                foreach (UIElement ue in this.mainTextPanel.Children)
                {
                    TextBlock tbk = ue as TextBlock;
                    if (tbk == null) continue;

                    if (tbk.TextWrapping != TextWrapping.Wrap)
                    {
                        tbk.TextWrapping = TextWrapping.Wrap;
                    }
                }
            }
            else
            {
                this.mainTextPanel.Width = double.NaN;

                foreach (UIElement ue in this.mainTextPanel.Children)
                {
                    TextBlock tbk = ue as TextBlock;
                    if (tbk == null) continue;

                    if (tbk.TextWrapping != TextWrapping.NoWrap)
                    {
                        tbk.TextWrapping = TextWrapping.NoWrap;
                    }
                }
            }
        }

        /// <summary>
        /// 刷新矩形的线宽。
        /// </summary>
        public override void RefreshWidgetLineWidth()
        {
            mainRectangle.StrokeThickness = widgetLineWidth;

            if (this.fixTextWidth)
            {
                RefreshTextPanelLocatin();
            }
        }

        private FrameworkElement xamlIconFrameWorkElement = null;

        /// <summary>
        /// 刷新IconXamlText(载入图标）。
        /// </summary>
        /// <returns>如果正常执行，返回string.Empty。否则返回异常信息。</returns>
        private void RefreshIconXamlText()
        {
            if (this.mainCanvas.Children.Contains(xamlIconFrameWorkElement))
            {
                this.mainCanvas.Children.Remove(xamlIconFrameWorkElement);
                xamlIconFrameWorkElement = null;
            }

            if (this.iconXamlText != null && this.iconXamlText.Length > 0)
            {
                byte[] array = System.Text.Encoding.UTF8.GetBytes(this.iconXamlText);

                try
                {
                    using (var stream = new System.IO.MemoryStream(array))
                    {
                        this.xamlIconFrameWorkElement = System.Windows.Markup.XamlReader.Load(stream) as FrameworkElement;
                        
                        Canvas.SetLeft(this.xamlIconFrameWorkElement, this.OuterRect.Left);
                        Canvas.SetTop(this.xamlIconFrameWorkElement, this.OuterRect.Top);

                        this.xamlIconFrameWorkElement.Width = this.OuterRect.Width;
                        this.xamlIconFrameWorkElement.Height = this.OuterRect.Height;

                        this.mainCanvas.Children.Add(this.xamlIconFrameWorkElement);
                    }
                }
                catch (Exception ex)
                {
                    throw ex;//异常不能在此处处理，否则SetRantangleXamlText.Execute()方法啥的就没法子处理异常了。
                }
            }
        }

        public override void RefreshLocation()
        {
            base.RefreshLocation();

            DrawLine();

            //Point startBasePt = StartBasePoint;
            //Point endBasePt = EndBasePoint;
            //Canvas.SetLeft(mainRectangle, startBasePt.X);
            //Canvas.SetTop(mainRectangle, startBasePt.Y);

            //mainRectangle.Width = (endBasePt.X - startBasePt.X);
            //mainRectangle.Height = (endBasePt.Y - startBasePt.Y);

            //this.movingRect = new Rect(startPoint, endPoint);

            RefreshWidgetLineWidth();

            RefreshMarkText();
            RefreshRadius(this.OuterRect);
            RefreshIconXamlText();
        }

        public void RefreshMarkText(Rect? rect = null)
        {
            if (this.markAdorner == null) return;

            if (string.IsNullOrEmpty(this.markText))
            {
                this.markAdorner.InvalidateVisual(); return;
            }

            if (rect == null)
            {
                this.markAdorner.MasterRect = this.RealRect;
            }
            else
            {
                this.markAdorner.MasterRect = rect.Value;
            }
            this.markAdorner.InvalidateVisual();
        }

        public void RefreshIsPresentationArea(Rect? rect = null)
        {
            if (this.presentationAreaAdorner == null) return;

            if (isPresentationArea)
            {
                this.presentationAreaAdorner.Visibility = Visibility.Visible;
            }
            else
            {
                this.presentationAreaAdorner.Visibility = Visibility.Hidden;
            }

            if (rect == null)
            {
                this.presentationAreaAdorner.MasterRect = this.RealRect;
            }
            else
            {
                this.presentationAreaAdorner.MasterRect = rect.Value;
            }

            this.presentationAreaAdorner.InvalidateVisual();

            if (isPresentationArea)
            {
                this.mainRectangle.Fill = null;
                this.mainRectangle.StrokeDashArray = LineDashType.dashCollection;
            }
            else
            {
                RefreshWidgetBackColor();
                RefreshLineDash();
            }
        }

        public override void RefreshPointWhenGroupIn(Point baseTopLeft)
        {
            Point oldStartPoint = startPoint;
            Point newStartPoint = new Point(oldStartPoint.X - baseTopLeft.X,
                oldStartPoint.Y - baseTopLeft.Y);
            StartPoint = newStartPoint;

            Point oldEndPoint = endPoint;
            Point newEndPoint = new Point(oldEndPoint.X - baseTopLeft.X,
                oldEndPoint.Y - baseTopLeft.Y);
            EndPoint = newEndPoint;
        }

        public override void RefreshPointWhenGroupOut(Point baseTopLeft)
        {
            Point oldStartPoint = startPoint;
            Point newStartPoint = new Point(oldStartPoint.X + baseTopLeft.X,
                oldStartPoint.Y + baseTopLeft.Y);
            StartPoint = newStartPoint;

            Point oldEndPoint = endPoint;
            Point newEndPoint = new Point(oldEndPoint.X + baseTopLeft.X,
                oldEndPoint.Y + baseTopLeft.Y);
            EndPoint = newEndPoint;
        }

        public void RefreshRadius(Rect rect)
        {
            if (this.mainRectangle == null) return;
            if (radius > 0)
            {
                double k = (radius % 1);//取小数。
                if (k == 0) k = 1;

                double r = Math.Min(rect.Width, rect.Height) * k;

                this.mainRectangle.RadiusX =
                    this.mainRectangle.RadiusY = r;
            }
            else
            {
                this.mainRectangle.RadiusX =
                 this.mainRectangle.RadiusY = 0;
            }
        }

        public override void RefreshIsShadowVisible()
        {
            //base.RefreshIsShadowVisible();//保持文本清晰

            if (isShadowVisible)
            {
                this.mainRectangle.Effect = Widget.ShadowEffect;
            }
            else
            {
                this.mainRectangle.Effect = null;
            }
        }

        public override void RefreshTextPanelLocatin()
        {
            LocateTextPanel(this.StartBasePoint, this.EndBasePoint);
        }

        /// <summary>
        /// 刷新文本区旋转角度。
        /// </summary>
        public void RefreshTextRotateAngle()
        {
            if (this.mainTextPanel.RenderTransformOrigin != DefaultRenderCenter)
            {
                this.mainTextPanel.RenderTransformOrigin = DefaultRenderCenter;
            }

            if (this.textRotateAngle == 0)
            {
                this.mainTextPanel.RenderTransform = DefaultRotateTransform;
            }
            else
            {
                this.mainTextPanel.RenderTransform = new RotateTransform(textRotateAngle);
            }
        }

        public override void RefreshWidgetBackColor()
        {
            base.RefreshWidgetBackColor();
            if (widgetBackColor == Brushes.Transparent)
            {
                this.mainRectangle.Fill = null;
            }
            else
            {
                this.mainRectangle.Fill = widgetBackColor;
            }

            //矩形要考虑气泡
            this.RefreshTextPanelLocatin();
        }

        public override void RefreshWidgetLineColor()
        {
            this.mainRectangle.Stroke = widgetLineColor;
        }
        
        #endregion


        #region 其它=========================================================================================================

        /// <summary>
        /// 表示拖动哪个控制点。
        /// </summary>
        private enum ControlDraggingType { Start, CenterCP, End, None }

        #endregion

    }
}
